package io.gitee.tziye.core.search;

import io.gitee.tziye.RenaiClient;
import io.gitee.tziye.common.RenaiUtil;
import io.gitee.tziye.enums.SearchType;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

public class RenaiSearch<T> {

    public final SearchOperator searchOperator;

    public final String module;
    public final Class<T> clazz;

    public RenaiSearch(RenaiClient renaiClient, String module, Class<T> clazz) {
        searchOperator = renaiClient.search();
        this.module = module;
        this.clazz = clazz;
    }

    public void save(RenaiText text) {
        text.setModule(module);
        searchOperator.save(text);
    }

    public void save(Collection<RenaiText> texts) {
        texts.forEach(text -> text.setModule(module));
        searchOperator.save(texts);
    }

    public void save(String businessId, T value) {
        searchOperator.save(new RenaiText(module, businessId, value));
    }

    public void save(Map<String, T> values) {
        List<RenaiText> texts = new ArrayList<>();
        values.forEach((k, v) -> texts.add(new RenaiText(module, k, v)));
        searchOperator.save(texts);
    }

    public boolean delete(String businessId) {
        return searchOperator.delete(module, businessId);
    }

    public int delete(Collection<String> businessIds) {
        return searchOperator.delete(module, businessIds);
    }

    public void drop() {
        searchOperator.drop(module);
    }

    public List<RenaiText> matchText(String word) {
        return searchOperator.search(module, SearchType.natural, word, true, 0, 100);
    }

    public List<RenaiText> matchText(List<String> words) {
        return searchOperator.search(module, SearchType.natural, words, true, 0, 100);
    }

    public List<RenaiText> matchText(String word, int start, int count) {
        return searchOperator.search(module, SearchType.natural, word, true, start, count);
    }

    public List<RenaiText> matchText(List<String> words, int start, int count) {
        return searchOperator.search(module, SearchType.natural, words, true, start, count);
    }

    public List<T> match(String word) {
        List<RenaiText> result = searchOperator.search(module, SearchType.natural, word, true, 0, 100);
        return result.stream().map(r -> RenaiUtil.parse(r.getContent(), clazz)).toList();
    }

    public List<T> match(List<String> words) {
        List<RenaiText> result = searchOperator.search(module, SearchType.natural, words, true, 0, 100);
        return result.stream().map(r -> RenaiUtil.parse(r.getContent(), clazz)).toList();
    }

    public List<T> match(String word, int start, int count) {
        List<RenaiText> result = searchOperator.search(module, SearchType.natural, word, true, start, count);
        return result.stream().map(r -> RenaiUtil.parse(r.getContent(), clazz)).toList();
    }

    public List<T> match(List<String> words, int start, int count) {
        List<RenaiText> result = searchOperator.search(module, SearchType.natural, words, true, start, count);
        return result.stream().map(r -> RenaiUtil.parse(r.getContent(), clazz)).toList();
    }

    public List<String> matchId(String word) {
        List<RenaiText> result = searchOperator.search(module, SearchType.natural, word, false, 0, 100);
        return result.stream().map(RenaiText::getBusinessId).toList();
    }

    public List<String> matchId(List<String> words) {
        List<RenaiText> result = searchOperator.search(module, SearchType.natural, words, false, 0, 100);
        return result.stream().map(RenaiText::getBusinessId).toList();
    }

    public List<String> matchId(String word, int start, int count) {
        List<RenaiText> result = searchOperator.search(module, SearchType.natural, word, false, start, count);
        return result.stream().map(RenaiText::getBusinessId).toList();
    }

    public List<String> matchId(List<String> words, int start, int count) {
        List<RenaiText> result = searchOperator.search(module, SearchType.natural, words, false, start, count);
        return result.stream().map(RenaiText::getBusinessId).toList();
    }

    public RenaiBoolSearch<T> bool() {
        return new RenaiBoolSearch<>(this);
    }

    public List<RenaiText> expansionText(String word) {
        return searchOperator.search(module, SearchType.expansion, word, true, 0, 100);
    }

    public List<RenaiText> expansionText(String word, int start, int count) {
        return searchOperator.search(module, SearchType.expansion, word, true, start, count);
    }

    public List<T> expansion(String word) {
        List<RenaiText> result = searchOperator.search(module, SearchType.expansion, word, true, 0, 100);
        return result.stream().map(r -> RenaiUtil.parse(r.getContent(), clazz)).toList();
    }

    public List<T> expansion(String word, int start, int count) {
        List<RenaiText> result = searchOperator.search(module, SearchType.expansion, word, true, start, count);
        return result.stream().map(r -> RenaiUtil.parse(r.getContent(), clazz)).toList();
    }

    public List<String> expansionId(String word) {
        List<RenaiText> result = searchOperator.search(module, SearchType.expansion, word, false, 0, 100);
        return result.stream().map(RenaiText::getBusinessId).toList();
    }

    public List<String> expansionId(String word, int start, int count) {
        List<RenaiText> result = searchOperator.search(module, SearchType.expansion, word, false, start, count);
        return result.stream().map(RenaiText::getBusinessId).toList();
    }

    public List<RenaiText> scriptText(String script) {
        return searchOperator.search(module, script, true, 0, 100);
    }

    public List<RenaiText> scriptText(String script, int start, int count) {
        return searchOperator.search(module, script, true, start, count);
    }

    public List<T> script(String script) {
        List<RenaiText> result = searchOperator.search(module, script, true, 0, 100);
        return result.stream().map(r -> RenaiUtil.parse(r.getContent(), clazz)).toList();
    }

    public List<T> script(String script, int start, int count) {
        List<RenaiText> result = searchOperator.search(module, script, true, start, count);
        return result.stream().map(r -> RenaiUtil.parse(r.getContent(), clazz)).toList();
    }

    public List<String> scriptId(String script) {
        List<RenaiText> result = searchOperator.search(module, script, false, 0, 100);
        return result.stream().map(RenaiText::getBusinessId).toList();
    }

    public List<String> scriptId(String script, int start, int count) {
        List<RenaiText> result = searchOperator.search(module, script, false, start, count);
        return result.stream().map(RenaiText::getBusinessId).toList();
    }
}